# 抽象类

  • 面向对象概念中,对象都是通过类来描述,但并不是所有类都是用来描绘对象的
  • 除了不能实例化对象外,抽象类与普通类并没有区别
  • 抽象类对子类有所要求: 可以强制子类对某些方法进行实现(覆写)

# 抽象类特性

  • 抽象类不能被实例化对象,必须被继承才能使用
  • 抽象类的子类需要实现所有的抽象方法,否则也是抽象类
  • 构造方法类方法(静态方法)不能声明为抽象方法
  • 一个类只能继承一个抽象类

注意

  • 抽象类允许不包含抽象方法,但依然不能被实例化
  • 子类对抽象方法的实现属于重写 (@Override)
  • 日常开发通常不会继承普通类,只继承抽象类

# 接口

  • 接口并不是类,类描述对象属性和方法,接口则是类要实现的抽象方法的集合
  • 抽象类虽然可以要求子类实现某些抽象方法,但是一个子类只能继承一个抽象类,却可以实现多个接口
  • 通常接口只包含全局常量抽象方法,即方法默认都是 public abstract,成员变量默认都是 public static final,但是从 JDK1.8 开始,接口可以定义更多的内容

# 接口特性

  • 接口不能实例化,需要由其他类实现接口
  • 接口的实现类(如果不是抽象类),必须实现接口中所有的「抽象」方法
  • 接口中每一个方法会被隐式指定为public abstract(只能是,其他修饰符会报错)
  • 接口中每一个变量会被隐式指定为public static final(接口中只有 public 一种权限)
  • 接口允许多继承,一个接口可以继承多个父接口

提示

接口可以用于标记(tag): 可以声明一个接口,无任何抽象方法,仅仅起到标记作用

# 接口定义的加强

JDK1.8 后,增加 default 方法和 static 方法定义(接口可以拥有方法体了)

  • default:作用范围也是 public,只是有了具体实现的方法体(需要实例才可以调用)
  • static:和类的静态方法一样,不需要实例,就可以直接调用

接口问题分析: 如果一个接口已经被多个类实现,但是又需要对接口进行修改,如扩充一个新方法,且所有子类对扩充方法的实现相同,此时就需要对大量子类进行修改

传统解决方案: 子类实现接口,同时在接口与子类间,增加一个中间抽象类,由抽象类「继承」接口

interface Person {}
public abstract StudentAdaptor implements Person {} // 中间类,负责一些同一的修改,实现
public student extends StudentAdaptor implements Person {}
1
2
3

JDK1.8之后考虑到了接口的修改扩充问题,为了简化抽象类的过渡造成的结构影响(结构混乱),所以引入了普通方法的定义


 




interface Person {
    public default sayHi {
        System.out.println("Hi");
    }
}
1
2
3
4
5

注意

但是因此也引出了新的问题,如果一个类实现了多个接口,而多个接口含有名称相同的default方法?相当于出现了「多继承」的问题,此时如果子类没有显示重写此方法,则编译器会报错

# 抽象类与接口

# 向上转型

一个类可以继承一个抽象类的同时,实现多个接口,且因为抽象类和接口都支持向上转型,因此子类的父类对象可以相互间进行强制类型转换



 

class Student extends BUStudent implements Person {}
BUStudent astu = new Student();
Person p = (Person) astu;  // Forced cast
1
2
3

Object类

由此可知,不仅所有引用数据类型(基本数据类型通过自动装箱也可以)可以由Object类接收,任何接口类型同样可以

# 区别

比较点 抽象类 接口
定义 abstract class interface
组成 属性,全局常量,构造/抽象/普通/静态方法 全局常量,抽象/普通/静态方法
关系 可以实现多个接口 不能继承任何类,可以继承多个父接口
子类 使用extends继承一个抽象类 使用implements实现多个接口
限制 单继承限制 无类似限制

可以发现,抽象类与接口的最大区别在于单继承限制上,两者皆可使用的情况下,优先使用接口

# 参考

[1] Java菜鸟教程 (opens new window)

[2] 阿里云大学 | 李兴华 - Java语言基础 (opens new window)

Last Updated: 9/4/2020, 9:34:54 PM